package org.karelun.gef.actions;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.SWTGraphics;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.karelun.gef.editors.IUmlEditorPart;
import org.karelun.gef.helper.ConstantMessages;
import org.karelun.gef.helper.IDConstant;
import org.karelun.gef.helper.ImageResource;

public class ExportImageAction extends Action {

	private class RunnableWithProgress implements IRunnableWithProgress {
		private String filePath;
		private int imgFormat;

		public RunnableWithProgress(String filePath, int imgFormat) {
			this.filePath = filePath;
			this.imgFormat = imgFormat;
		}

		public void run(IProgressMonitor monitor)
				throws InvocationTargetException, InterruptedException {
			
			monitor.beginTask(ConstantMessages.ExportImageShell_Label, 100);
			IEditorPart activeEditor = window.getActivePage().getActiveEditor();
			if (!(activeEditor instanceof IUmlEditorPart))
				return;
			IUmlEditorPart editor = (IUmlEditorPart) activeEditor;
			RootEditPart rootEditPart = editor.getViewer().getRootEditPart();
			
			if(!(rootEditPart instanceof ScalableFreeformRootEditPart))
				return;
			ScalableFreeformRootEditPart rootPart=(ScalableFreeformRootEditPart)rootEditPart;
			IFigure layer = rootPart.getLayer(ScalableFreeformRootEditPart.PRINTABLE_LAYERS);
			
			for (int i = 0; i < 4 && !monitor.isCanceled(); i++) {
				Thread.sleep(500);
				monitor.worked(25);
			}

			byte[] data = createImage(layer, imgFormat);
			try {
				FileOutputStream os = new FileOutputStream(filePath);
				os.write(data);
				os.close();
			} catch (IOException e) {
			}
			monitor.done();
		}

	}

	private IWorkbenchWindow window;

	public ExportImageAction(IWorkbenchWindow window) {
		this.window = window;
		setId(IDConstant.ExportImageAction_Id);
		setImageDescriptor(ImageResource
				.getImageDesc(ImageResource.EXPORT_IMAGE));
		setText(ConstantMessages.exportImage_Text);
		setActionDefinitionId(IDConstant.ExportImageAction_CMD_ID);
	}

	public void run() {
		FileDialog dialog = openDialog();
		String filePath = dialog.open();
		if(filePath==null)
			return;
		int index = dialog.getFilterIndex();
		int imgFormat = getImageFormat(index);

		ProgressMonitorDialog proDialog = new ProgressMonitorDialog(window
				.getShell());
		RunnableWithProgress runnable = new RunnableWithProgress(filePath,
				imgFormat);
		try {
			proDialog.run(true, true, runnable);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		Program.launch(filePath);
	}

	private byte[] createImage(IFigure layer, int imageFormat) {
		Rectangle rect = layer.getBounds();
		ByteArrayOutputStream in = new ByteArrayOutputStream();
		Image image = null;
		GC gc = null;
		Graphics g = null;
		try {
			image = new Image(null, rect.width, rect.height);
			gc = new GC(image);
			g = new SWTGraphics(gc);
			g.translate(rect.x - 1, rect.y - 1);
			layer.paint(g);
			ImageLoader imageLoader = new ImageLoader();
			imageLoader.data = new ImageData[] { image.getImageData() };
			imageLoader.save(in, imageFormat);
		} finally {
			if (g != null)
				g.dispose();
			if (gc != null)
				gc.dispose();
			if (image != null)
				image.dispose();
		}
		return in.toByteArray();
	}

	private int getImageFormat(int index) {
		switch (index) {
		case 0:
			return SWT.IMAGE_PNG;
		case 1:
			return SWT.IMAGE_JPEG;
		case 2:
			return SWT.IMAGE_BMP;
		}
		return 0;
	}

	private FileDialog openDialog() {
		FileDialog dialog = new FileDialog(window.getShell(), SWT.SAVE);
		dialog.setText(ConstantMessages.ExportImageDialog_Title);
		dialog.setFilterExtensions(new String[] { "*.png", "*.jpg", "*.bmp" }); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
		dialog.setFilterNames(new String[] { "diagram(*.png)", //$NON-NLS-1$
				"diagram(*.jpg)", "diagram(*.bmp)" }); //$NON-NLS-1$//$NON-NLS-2$
		return dialog;
	}
}
